package com.starrocks.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.UUID;

/**
 * ID生成器
 * 支持多种ID生成策略
 */
@Slf4j
@Component
public class IdGenerator {
    
    /**
     * 雪花算法生成器（简化版）
     */
    private static final SnowflakeIdWorker SNOWFLAKE = new SnowflakeIdWorker(1, 1);
    
    /**
     * 根据策略生成ID
     * 
     * @param strategy ID生成策略：AUTO_INCREMENT、UUID、SNOWFLAKE
     * @return 生成的ID值
     */
    public Object generateId(String strategy) {
        if (strategy == null || strategy.trim().isEmpty()) {
            return null; // 策略为空，使用数据库默认值（如AUTO_INCREMENT）
        }
        
        switch (strategy.toUpperCase()) {
            case "AUTO_INCREMENT":
                // AUTO_INCREMENT由数据库自动处理，返回null表示不设置
                return null;
                
            case "UUID":
                return UUID.randomUUID().toString().replace("-", "");
                
            case "SNOWFLAKE":
                return SNOWFLAKE.nextId();
                
            default:
                log.warn("未知的ID生成策略: {}, 将使用数据库默认值", strategy);
                return null;
        }
    }
    
    /**
     * 雪花算法ID生成器（简化版）
     * 来源：Twitter Snowflake
     */
    private static class SnowflakeIdWorker {
        
        // 起始时间戳 (2024-01-01)
        private final long twepoch = 1704067200000L;
        
        // 机器ID所占的位数
        private final long workerIdBits = 5L;
        
        // 数据标识ID所占的位数
        private final long datacenterIdBits = 5L;
        
        // 序列号所占的位数
        private final long sequenceBits = 12L;
        
        // 机器ID向左移12位
        private final long workerIdShift = sequenceBits;
        
        // 数据中心ID向左移17位
        private final long datacenterIdShift = sequenceBits + workerIdBits;
        
        // 时间戳向左移22位
        private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
        
        // 生成序列的掩码
        private final long sequenceMask = ~(-1L << sequenceBits);
        
        // 工作机器ID(0~31)
        private long workerId;
        
        // 数据中心ID(0~31)
        private long datacenterId;
        
        // 毫秒内序列(0~4095)
        private long sequence = 0L;
        
        // 上次生成ID的时间戳
        private long lastTimestamp = -1L;
        
        /**
         * 构造函数
         * @param workerId 工作ID (0~31)
         * @param datacenterId 数据中心ID (0~31)
         */
        public SnowflakeIdWorker(long workerId, long datacenterId) {
            long maxWorkerId = ~(-1L << workerIdBits);
            long maxDatacenterId = ~(-1L << datacenterIdBits);
            
            if (workerId > maxWorkerId || workerId < 0) {
                throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
            }
            if (datacenterId > maxDatacenterId || datacenterId < 0) {
                throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
            }
            this.workerId = workerId;
            this.datacenterId = datacenterId;
        }
        
        /**
         * 获得下一个ID (线程安全)
         */
        public synchronized long nextId() {
            long timestamp = timeGen();
            
            // 如果当前时间小于上一次ID生成的时间戳，说明系统时钟回退过
            if (timestamp < lastTimestamp) {
                throw new RuntimeException(
                    String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", 
                        lastTimestamp - timestamp));
            }
            
            // 如果是同一时间生成的，则进行毫秒内序列
            if (lastTimestamp == timestamp) {
                sequence = (sequence + 1) & sequenceMask;
                // 毫秒内序列溢出
                if (sequence == 0) {
                    // 阻塞到下一个毫秒,获得新的时间戳
                    timestamp = tilNextMillis(lastTimestamp);
                }
            }
            // 时间戳改变，毫秒内序列重置
            else {
                sequence = 0L;
            }
            
            // 上次生成ID的时间戳
            lastTimestamp = timestamp;
            
            // 移位并通过或运算拼到一起组成64位的ID
            return ((timestamp - twepoch) << timestampLeftShift)
                | (datacenterId << datacenterIdShift)
                | (workerId << workerIdShift)
                | sequence;
        }
        
        /**
         * 阻塞到下一个毫秒，直到获得新的时间戳
         */
        protected long tilNextMillis(long lastTimestamp) {
            long timestamp = timeGen();
            while (timestamp <= lastTimestamp) {
                timestamp = timeGen();
            }
            return timestamp;
        }
        
        /**
         * 返回以毫秒为单位的当前时间
         */
        protected long timeGen() {
            return System.currentTimeMillis();
        }
    }
}

